package com.ocean.web.util.rwdata;

import com.ocean.system.domain.SeaTempNcMetadata;
import ucar.ma2.Array;
import ucar.nc2.Attribute;
import ucar.nc2.NetcdfFile;
import ucar.nc2.Variable;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;

/**
 * 全球海温 NC 文件元数据读取工具（适配 netcdfAll-5.4.1）
 * 核心功能：要素名称elements返回短名称（分号隔开）
 */
public class GlobalSstNcReader_5_4_1 {

    // 时间格式工具（处理 UTC 时间）
    private static final SimpleDateFormat UTC_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    static {
        UTC_FORMAT.setTimeZone(TimeZone.getTimeZone("UTC"));
    }

    /**
     * 核心方法：读取海温 NC 文件元数据，返回实体类（要素名称为短名称）
     * @param ncFilePath NC 文件路径（本地文件）
     * @return 海温 NC 元数据实体类
     * @throws IOException NC 文件读取异常
     */
    public SeaTempNcMetadata readMetadataToEntity(String ncFilePath) throws IOException {
        // 前置校验：路径非空+文件存在
        if (ncFilePath == null || ncFilePath.trim().isEmpty()) {
            throw new IllegalArgumentException("NC文件路径不能为空！");
        }
        File ncFile = new File(ncFilePath);
        if (!ncFile.exists() || !ncFile.isFile()) {
            throw new IOException("NC文件不存在或非法：" + ncFilePath);
        }

        try (NetcdfFile file = NetcdfFile.open(ncFilePath)) {
            // 1. NC文件名
            String ncFileName = extractFileName(ncFilePath);

            // 2. 来源
            String source = getGlobalAttrValue(file, "source", "unknown");
            if ("unknown".equals(source)) {
                source = getGlobalAttrValue(file, "institution", "unknown");
            }

            // 3. 类型
            String type = "全球海表温度（SST）";

            // 4. 起报时间
            String forecastBaseTime = parseForecastBaseTime(file);

            // 5. 预报时效
            String forecastLeadTime = parseForecastLeadTime(file);

            // 6. 预报频次
            String forecastFreq = parseForecastFreq(file);

            // 7. 覆盖范围
            String coverage = "全球海洋（纬度：" + getLatRange(file) + "，经度：" + getLonRange(file) + "）";

            // 8. 空间分辨率
            String spatialRes = calculateSpatialResolution(file);

            // 9. 要素名称elements（短名称，分号隔开）- 核心修改
            String elements = getSeaTempShortNames(file);

            // 构建并返回实体类
            return new SeaTempNcMetadata(
                    ncFileName,
                    source,
                    type,
                    forecastBaseTime,
                    forecastLeadTime,
                    forecastFreq,
                    coverage,
                    spatialRes,
                    elements
            );
        }
    }

    // ---------------------- 核心方法：提取要素短名称（分号隔开）----------------------
    /**
     * 提取海温要素短名称（纯变量名，分号隔开）
     * 适配：变量名含下划线则取第一部分（如 sst_10m → sst），自动去重
     */
    private String getSeaTempShortNames(NetcdfFile ncFile) {
        // 常见海温变量名（可根据实际文件扩展）
        String[] targetVarNames = {"sst", "tos", "sea_surface_temperature", "temperature_at_sea_surface"};
        StringBuilder shortNames = new StringBuilder();

        for (String varName : targetVarNames) {
            Variable var = ncFile.findVariable(varName);
            if (var == null) {
                continue; // 变量不存在则跳过，避免空指针
            }

            // 提取短名称：先取变量的shortName
            String shortName = var.getShortName();
            // 处理下划线后缀（如 "sst_10maboveground" → "sst"）
            if (shortName.contains("_")) {
                shortName = shortName.split("_")[0].trim();
            }
            // 避免重复添加同一短名称
            if (shortNames.indexOf(shortName) == -1) {
                shortNames.append(shortName).append(";");
            }
        }

        // 移除最后一个分号，为空则返回默认值
        if (shortNames.length() > 0) {
            return shortNames.substring(0, shortNames.length() - 1);
        } else {
            return "未识别到要素短名称";
        }
    }

    // ---------------------- 原有工具方法（保持不变，仅保留核心）----------------------
    private String extractFileName(String fileLocation) {
        if (fileLocation == null || fileLocation.isEmpty()) {
            return "unknown_filename.nc";
        }
        fileLocation = fileLocation.replace("\\", "/");
        int lastSlashIndex = fileLocation.lastIndexOf("/");
        return lastSlashIndex == -1 ? fileLocation : fileLocation.substring(lastSlashIndex + 1);
    }

    private String getGlobalAttrValue(NetcdfFile ncFile, String attrName, String defaultValue) {
        Attribute attr = ncFile.findGlobalAttribute(attrName);
        return attr != null ? attr.getStringValue().trim() : defaultValue;
    }

    private String parseForecastBaseTime(NetcdfFile ncFile) {
        String baseTimeStr = getGlobalAttrValue(ncFile, "forecast_reference_time", null);
        if (baseTimeStr != null) {
            return formatTimeString(baseTimeStr);
        }
        baseTimeStr = getGlobalAttrValue(ncFile, "base_time", null);
        if (baseTimeStr != null) {
            return formatTimeString(baseTimeStr);
        }

        Variable timeVar = ncFile.findVariable("time");
        if (timeVar == null) {
            timeVar = ncFile.findVariable("forecast_time");
        }
        if (timeVar == null) {
            return "未知";
        }

        try {
            Array timeArray = timeVar.read(new int[]{0}, new int[]{1});
            double timeValue = timeArray.getDouble(0);
            String timeUnit = getGlobalAttrValue(timeVar.getNetcdfFile(), "units", "hours since 1970-01-01 00:00:00");
            return parseTimeFromUnit(timeValue, timeUnit);
        } catch (Exception e) {
            return "解析失败";
        }
    }

    private String parseForecastLeadTime(NetcdfFile ncFile) {
        Variable timeVar = ncFile.findVariable("time");
        if (timeVar == null) {
            timeVar = ncFile.findVariable("forecast_time");
        }
        if (timeVar == null) {
            return "未知";
        }

        try {
            int timeLen = timeVar.getShape()[0];
            if (timeLen <= 1) {
                return "0小时（分析场）";
            }

            Array timeArray = timeVar.read();
            double first = timeArray.getDouble(0);
            double second = timeArray.getDouble(1);
            double interval = second - first;

            String timeUnit = getGlobalAttrValue(timeVar.getNetcdfFile(), "units", "hours");
            String unitStr = timeUnit.contains("day") ? "天" : timeUnit.contains("hour") ? "小时" : "未知单位";
            double totalLead = interval * (timeLen - 1);

            return String.format("%.0f%s（%d个时次）", totalLead, unitStr, timeLen);
        } catch (Exception e) {
            return "解析失败";
        }
    }

    private String parseForecastFreq(NetcdfFile ncFile) {
        Variable timeVar = ncFile.findVariable("time");
        if (timeVar == null) {
            timeVar = ncFile.findVariable("forecast_time");
        }
        if (timeVar == null) {
            return "未知";
        }

        try {
            if (timeVar.getShape()[0] <= 1) {
                return "单次（分析场）";
            }

            Array timeArray = timeVar.read();
            double interval = timeArray.getDouble(1) - timeArray.getDouble(0);
            String timeUnit = getGlobalAttrValue(timeVar.getNetcdfFile(), "units", "hours");

            if (timeUnit.contains("day")) {
                return interval == 1 ? "每日1次" : String.format("每%.0f天1次", interval);
            } else if (timeUnit.contains("hour")) {
                if (interval == 6) return "每6小时1次";
                if (interval == 12) return "每12小时1次";
                if (interval == 24) return "每日1次";
                return String.format("每%.0f小时1次", interval);
            } else {
                return String.format("每%.0f%s1次", interval, timeUnit.split(" ")[0]);
            }
        } catch (Exception e) {
            return "解析失败";
        }
    }

    private String getLatRange(NetcdfFile ncFile) {
        Variable latVar = ncFile.findVariable("lat");
        if (latVar == null) {
            latVar = ncFile.findVariable("latitude");
        }
        if (latVar == null) {
            return "未知";
        }

        try {
            Array latArray = latVar.read();
            double minLat = latArray.getDouble(0);
            double maxLat = latArray.getDouble((int) (latArray.getSize() - 1));
            if (minLat > maxLat) {
                double temp = minLat;
                minLat = maxLat;
                maxLat = temp;
            }
            return String.format("%.2f°S - %.2f°N", minLat, maxLat);
        } catch (Exception e) {
            return "解析失败";
        }
    }

    private String getLonRange(NetcdfFile ncFile) {
        Variable lonVar = ncFile.findVariable("lon");
        if (lonVar == null) {
            lonVar = ncFile.findVariable("longitude");
        }
        if (lonVar == null) {
            return "未知";
        }

        try {
            Array lonArray = lonVar.read();
            double minLon = lonArray.getDouble(0);
            double maxLon = lonArray.getDouble((int) (lonArray.getSize() - 1));
            if (minLon < 0) {
                return String.format("%.2f°W - %.2f°E", Math.abs(minLon), maxLon);
            } else {
                return String.format("%.2f°E - %.2f°E", minLon, maxLon);
            }
        } catch (Exception e) {
            return "解析失败";
        }
    }

    private String calculateSpatialResolution(NetcdfFile ncFile) {
        String latRes = "未知";
        String lonRes = "未知";

        Variable latVar = ncFile.findVariable("lat");
        if (latVar == null) latVar = ncFile.findVariable("latitude");
        if (latVar != null) {
            try {
                Array latArray = latVar.read();
                if (latArray.getSize() >= 2) {
                    double interval = Math.abs(latArray.getDouble(1) - latArray.getDouble(0));
                    latRes = String.format("%.2f°", interval);
                }
            } catch (Exception e) {
                latRes = "解析失败";
            }
        }

        Variable lonVar = ncFile.findVariable("lon");
        if (lonVar == null) lonVar = ncFile.findVariable("longitude");
        if (lonVar != null) {
            try {
                Array lonArray = lonVar.read();
                if (lonArray.getSize() >= 2) {
                    double interval = Math.abs(lonArray.getDouble(1) - lonArray.getDouble(0));
                    lonRes = String.format("%.2f°", interval);
                }
            } catch (Exception e) {
                lonRes = "解析失败";
            }
        }

        return String.format("纬度：%s，经度：%s", latRes, lonRes);
    }

    private String parseTimeFromUnit(double timeValue, String timeUnit) {
        try {
            String baseTimeStr = timeUnit.split("since ")[1].trim();
            Date baseDate = UTC_FORMAT.parse(baseTimeStr);

            long baseTimeMs = baseDate.getTime();
            if (timeUnit.contains("day")) {
                baseTimeMs += (long) (timeValue * 24 * 60 * 60 * 1000);
            } else if (timeUnit.contains("hour")) {
                baseTimeMs += (long) (timeValue * 60 * 60 * 1000);
            } else if (timeUnit.contains("minute")) {
                baseTimeMs += (long) (timeValue * 60 * 1000);
            } else if (timeUnit.contains("second")) {
                baseTimeMs += (long) (timeValue * 1000);
            }

            return UTC_FORMAT.format(new Date(baseTimeMs));
        } catch (Exception e) {
            return timeValue + " " + timeUnit;
        }
    }

    private String formatTimeString(String timeStr) {
        try {
            timeStr = timeStr.replace("T", " ").replace("Z", "").trim();
            if (timeStr.length() == 8) {
                timeStr = timeStr.substring(0, 4) + "-" + timeStr.substring(4, 6) + "-" + timeStr.substring(6, 8) + " 00:00:00";
            }
            Date date = UTC_FORMAT.parse(timeStr);
            return UTC_FORMAT.format(date);
        } catch (Exception e) {
            return timeStr;
        }
    }

    // 测试方法（验证短名称输出）
    public static void main(String[] args) {
        String ncFilePath = "E:\\项目资料备份\\新云平台文件\\2025工作\\样例数据-检验\\全球海温\\NMF_BEN_GO_GLDT_2025111800_168h_SST.nc";
        GlobalSstNcReader_5_4_1 reader = new GlobalSstNcReader_5_4_1();

        try {
            SeaTempNcMetadata metadata = reader.readMetadataToEntity(ncFilePath);
            System.out.println("全球海温 NC 文件元数据：");
            System.out.println(metadata);
            System.out.println("\n单独获取要素名称elements（短名称）：" + metadata.getElements());
        } catch (IOException e) {
            System.err.println("读取失败：" + e.getMessage());
            e.printStackTrace();
        }
    }
}